package com.youlu.campus.web.order.service;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.order.GoodsInfo;
import com.youlu.campus.base.order.enums.OrderPayTypeEnum;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.PlaceOrderReq;
import com.youlu.campus.entity.VO.req.QQMiniPlaceOrderReq;
import com.youlu.campus.entity.domain.WechatH5PayConfigDomain;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.item.ItemInfoService;
import com.youlu.campus.service.qq.QQConfigInfoService;
import com.youlu.campus.service.visitor.UserAddressInfoService;
import com.youlu.campus.service.wechat.WechatMerchantConfigService;
import com.youlu.campus.service.wechatpay.WechatPayCacheService;
import com.youlu.campus.web.order.entity.OrderPO;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Slf4j
@Service
public class QQMiniOrderService extends OrderBaseService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ItemInfoService itemInfoService;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private QQConfigInfoService qqConfigInfoService;
    @Autowired
    private WechatMerchantConfigService wechatMerchantConfigService;
    @Autowired
    private WechatPayCacheService wechatPayCacheService;
    @Autowired
    private UserAddressInfoService userAddressInfoService;

    public OrderInfo getOrderInfo(String orderNo) {
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        return mongoTemplate.findOne(query, OrderInfo.class);
    }

    public Map<String, String> placeOrder(QQMiniPlaceOrderReq req) {
        log.info(":>>> 下单req {}", JSON.toJSONString(req));
        UserPO userPO = req.getCurrentUser();
        checkPlaceOrder(req);
        ItemInfo itemInfo = itemInfoService.detail(req.getItemId());
        if (Objects.isNull(itemInfo)) {
            log.error(":.>> 商品不存在:{}", req.getItemId());
            throw new BusinessException("商品不存在");
        }
        if(Boolean.FALSE.equals(itemInfo.getOnSale())){
            log.error(":.>> 商品已经下架:{}", req.getItemId());
            throw new BusinessException("本商品已下架，请购买其它商品");
        }
        UserAddressInfo userAddressInfo = userAddressInfoService.findByUserId(req.getCurrentUser().getId());
        if (Objects.isNull(userAddressInfo)) {
            userAddressInfo = new UserAddressInfo();
            userAddressInfo.setArea(req.getArea());
            userAddressInfo.setProvince(req.getProvince());
            userAddressInfo.setCity(req.getCity());
            userAddressInfo.setFullAddress(req.getAddress());
            userAddressInfo.setUserId(req.getCurrentUser().getId());
            userAddressInfo.setCreatedTime(new Date());
            userAddressInfo.setRecieveName(req.getName());
            userAddressInfo.setRecieveMobile(req.getMobile());
            userAddressInfoService.create(userAddressInfo);
        }else {
            userAddressInfo.setArea(req.getArea());
            userAddressInfo.setProvince(req.getProvince());
            userAddressInfo.setCity(req.getCity());
            userAddressInfo.setFullAddress(req.getAddress());
            userAddressInfo.setUserId(req.getCurrentUser().getId());
            userAddressInfo.setCreatedTime(new Date());
            userAddressInfo.setRecieveName(req.getName());
            userAddressInfo.setRecieveMobile(req.getMobile());
            userAddressInfoService.update(userAddressInfo);
        }
        String orderNo = super.generateOrderNo("证书");
        if (super.resubmit(3L, userPO.getId(), orderNo)) {
            log.info(":>>> 有已经待支付的订单,请不要重复支付");
            throw new BusinessException("请勿重复发起支付~");
        }
        req.setTips(itemInfo.getOrderDeliveryTips());
        if("badge".equals(itemInfo.getCategory())){
            req.setItemCategory("badge");
        }
        req.getItemIds().add(req.getItemId());
        QQConfigInfo qqConfigInfo = qqConfigInfoService.findByAppId(req.getAppId());
        req.setWechatAppId(qqConfigInfo.getBindWechatAppId());
        OrderInfo orderInfo = generateOrder(req, orderNo);
        OrderPO orderPO = new OrderPO();
        orderPO.setTransactionId(orderNo);
        orderPO.setOrderNo(orderNo);
        orderPO.setOpenId(userPO.getOpenId());
        orderPO.setPlatform(req.getPlatform());
        orderPO.setPayType(OrderPayTypeEnum.WX.getCode());
        orderPO.setMerchantId(orderInfo.getMechantId());
        orderPO.setPayPrice(orderInfo.getTotalFee());
        String str = System.currentTimeMillis() + "";
        orderPO.setTimestampStr(str);
        orderPO.setNonceStr(str);
        orderPO.setClientIp(req.getClientIp());
        GoodsInfo goodsInfo = new GoodsInfo();
        if("badge".equals(itemInfo.getCategory())){
            goodsInfo.setGoodsName("徽章商品");
        }else{
            goodsInfo.setGoodsName("文创商品");
        }
        orderPO.setGoods(goodsInfo);
        orderPO.setAppId(req.getAppId());

        orderPO.setBindWechatAppId(qqConfigInfo.getBindWechatAppId());
        Map<String, String> result = new HashMap<>();
        //获取预支付参数
        QResult<Map<String, String>> uniOrderResult = super.getUniOrderResult(orderPO);
        log.info(":>>> 获取微信预支付参数结果为:{}", JSON.toJSONString(uniOrderResult));
        // 支付成功
        if (uniOrderResult.code == 0) {
            result = uniOrderResult.data;
            WechatPayCache cache = new WechatPayCache();
            cache.setOrderNo(orderNo);
            cache.setType("oid");
            cache.setBizType(req.getItemCategory());
            cache.setStatus(Boolean.FALSE);
            cache.setCreatedTime(new Date());
            wechatPayCacheService.create(cache);
        } else {
            log.info("placeOrder applyReq {} error msg {}", req, uniOrderResult.msg);
        }
        result.put("payFeeType", "1");
        result.put("payDesc", "微信支付");
        log.info(":>>> 微信支付参数为:{}", JSON.toJSONString(result));
        if ("wechat-h5".equals(orderPO.getPlatform())) {
            log.info(":>>> 平台是wechat-h5,设置JS SDK配置");
            WechatH5PayConfigDomain config = activityService.getPayConfig(userPO, req.getUrl(),
                    orderPO.getNonceStr(), orderPO.getTimestampStr());
            result.put("appId", config.getAppId());
            result.put("signature", config.getSignature());
            result.put("nonceStr", config.getNonceStr());
            result.put("timeStamp", config.getTimestamp());
            result.put("jsApiList", JSON.toJSONString(config.getJsApiList()));
        }
        // TODO:更新订单状态:等待回调
        log.info(":>>> 微信支付参数为:{}", JSON.toJSONString(result));
        return result;

    }

    @Override
    public Map<String, String> placeOrder(PlaceOrderReq req) {
        return null;
    }

    @Override
    public boolean handlePayNotify(OrderPO orderPO) {
        return false;
    }

    /**
     * 检查下单参数
     *
     * @param req
     */
    private void checkPlaceOrder(QQMiniPlaceOrderReq req) {
        if (StringUtils.isBlank(req.getItemId()) || StringUtils.isBlank(req.getName()) || StringUtils.isBlank(req.getMobile()) || StringUtils.isBlank(req.getProvince()) ||
                StringUtils.isBlank(req.getCity()) || StringUtils.isBlank(req.getArea()) || StringUtils.isBlank(req.getAddress())) {
            log.error(":>>> 支付参数错误");
            throw new BusinessException("支付参数错误");
        }
    }

    /**
     * 生成订单
     *
     * @param req
     * @param orderNo
     * @return
     */
    private OrderInfo generateOrder(QQMiniPlaceOrderReq req, String orderNo) {
        ActivityInfo activityInfo = null;
        if (StringUtils.isNotBlank(req.getActivityId())) {
            activityInfo = activityService.findOne(req.getActivityId());
        }
        Date date = new Date();
        OrderInfo orderInfo = new OrderInfo();
        QQConfigInfo qqConfigInfo = qqConfigInfoService.findByAppId(req.getAppId());
        if (Objects.isNull(qqConfigInfo) || StringUtils.isBlank(qqConfigInfo.getMerchantId())) {
            log.error(":>>> QQ小程序配置错误:{}", req.getAppId());
            throw new BusinessException("当前支付人数多,稍后重试");
        }
        WechatMerchantConfig merchantConfig = wechatMerchantConfigService.findByMerchantIdAndDecrypt(qqConfigInfo.getMerchantId());
        if (Objects.isNull(merchantConfig)) {
            log.error(":>>> 当前支付人数多,稍后重试,商户号配置错误:{}", qqConfigInfo.getMerchantId());
            throw new BusinessException("微信支付服务器异常,稍后重试");
        }
        orderInfo.setProvince(req.getProvince());
        orderInfo.setCity(req.getCity());
        orderInfo.setArea(req.getArea());
        orderInfo.setAddress(req.getAddress());
        orderInfo.setMobile(req.getMobile());
        orderInfo.setActivityId(req.getActivityId());
        orderInfo.setName(req.getName());
        orderInfo.setWechatAppId(req.getWechatAppId());
        orderInfo.setOrderNo(orderNo);
        orderInfo.setCreatedTime(date);
        orderInfo.setStatus("0");
        orderInfo.setActivityId(req.getActivityId());
        orderInfo.setAppId(req.getAppId());
        orderInfo.setOpenId(req.getOpenId());
        orderInfo.setPlatform(req.getPlatform());
        orderInfo.setCategory(req.getItemCategory());
        Integer price = 0;
        Integer num = 0;
        Integer totalPrice = 0;
        Integer expressFee = 0;
        Integer discountPrice = 0;
        String expressTips = "";
        for (String caId : req.getItemIds()) {
            ItemInfo caInfo = itemInfoService.detail(caId);
            if (Objects.isNull(caInfo)) {
                log.error(":>>> 商品不存在不存在:{}", caId);
                throw new BusinessException("商品不存在");
            }
            String oorderNo = super.generateOrderNo("证书子订单");
            OOrderInfo oOrderInfo = buildOOrderInfo(caInfo, req.getCurrentUser(), req.getActivityId(), orderNo, oorderNo, false);
            orderInfo.setTitle(caInfo.getTitle());
            orderInfo.setImageUrl(caInfo.getImageUrl());
            price = price + caInfo.getPrice();
            totalPrice = totalPrice + caInfo.getPrice();
            num = num + 1;
            oOrderInfo.setItemImageUrl(caInfo.getImageUrl());
            mongoTemplate.insert(oOrderInfo);
        }
        orderInfo.setTotalFee(totalPrice);
        orderInfo.setItemPrice(price);
        orderInfo.setNum(num);
        orderInfo.setExpressFee(expressFee);
        orderInfo.setDiscountFee(discountPrice);
        orderInfo.setAccountInfoId(req.getCurrentUser().getId());
        if(StringUtils.isNotBlank(req.getTips())){
            orderInfo.setTips(req.getTips());
        }else{
            if (Objects.nonNull(activityInfo)) {
                orderInfo.setTips(activityInfo.getOrderTips());
            }
        }
        orderInfo.setCreatedTime(new Date());
        orderInfo.setMechantId(merchantConfig.getMerchantId());
        orderInfo.setMechantName(merchantConfig.getMerchantName());
        orderInfo = mongoTemplate.insert(orderInfo);
        log.info(":>>> 订单:{},邮费提示语:{},证书配置提示语:{}", orderInfo.getOrderNo(), orderInfo.getExpressFeeTips(), expressTips);
        return orderInfo;
    }

    /**
     * 生成子订单
     *
     * @param caInfo
     * @param userPO
     * @param activityId
     * @param orderNo
     * @param oorderNo
     * @param gift
     * @return
     */
    private OOrderInfo buildOOrderInfo(ItemInfo caInfo, UserPO userPO,
                                       String activityId, String orderNo,
                                       String oorderNo, boolean gift) {
        OOrderInfo oOrderInfo = new OOrderInfo();
        oOrderInfo.setOrderNo(orderNo);
        oOrderInfo.setOOrderNo(oorderNo);
        oOrderInfo.setCreatedTime(new Date());
        oOrderInfo.setAccountInfoId(userPO.getId());
        oOrderInfo.setItemInfo(caInfo);
        oOrderInfo.setItemType("item");
        oOrderInfo.setItemInfoId(caInfo.getId());
        oOrderInfo.setStatus("0");
        oOrderInfo.setItemTitle(caInfo.getTitle());
        oOrderInfo.setImageUrl(caInfo.getImageUrl());
        oOrderInfo.setSalePrice(caInfo.getPrice());
        oOrderInfo.setAppId(userPO.getAppId());
        oOrderInfo.setOpenId(userPO.getOpenId());

        oOrderInfo.setPlatform(userPO.getCurrentPlatform());
        oOrderInfo.setNum(1);
        oOrderInfo.setOpenId(userPO.getOpenId());
        oOrderInfo.setActivityId(activityId);
        if (gift) {
            oOrderInfo.setGifted(true);
            oOrderInfo.setSalePrice(0);
            oOrderInfo.setItemPrice(0);
            oOrderInfo.setSalePriceBack(caInfo.getPrice());
            oOrderInfo.setItemPrice(0);
        } else {
            oOrderInfo.setGifted(false);
        }
        return oOrderInfo;
    }

}
